/*
 *  MenuGenerator, a free menu generator for microcontrollers
 *  Copyright (C) 2011  Erik Abrahamsson
 *
 *   This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package menugen;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.geom.Rectangle2D;
import java.net.URL;

import javax.swing.JPanel;

public class Emulator extends SettingsPanel implements MouseListener {

	private static final long serialVersionUID = 1L;
	String text = "";
	
	String[] buttons = {"back", "<-", "->", "enter"};
	Integer button_down = null;
	
	double scale;
	int lcd_height;
	
	final char font[][] = {
			{0x00, 0x00, 0x00, 0x00, 0x00}, // space
			{0x00, 0x00, 0x6f, 0x00, 0x00}, // !
			{0x00, 0x00, 0x07, 0x00, 0x07}, // "
			{0x14, 0x7f, 0x14, 0x7f, 0x14}, // #
			{0x24, 0x2a, 0x7f, 0x2a, 0x12}, // $
			{0x43, 0x33, 0x08, 0x66, 0x61}, // %
			{0x32, 0x4d, 0x59, 0x21, 0x72}, // &
			{0x00, 0x00, 0x03, 0x00, 0x00}, // '
			{0x00, 0x00, 0x3e, 0x41, 0x00}, // (
			{0x00, 0x41, 0x3e, 0x00, 0x00}, // )
			{0x0a, 0x0c, 0x07, 0x0c, 0x0a}, // *
			{0x08, 0x08, 0x3e, 0x08, 0x08}, // +
			{0x00, 0x00, 0xe0, 0x60, 0x00}, // ,
			{0x08, 0x08, 0x08, 0x08, 0x08}, // -
			{0x00, 0x00, 0x60, 0x60, 0x00}, // .
			{0x40, 0x30, 0x08, 0x06, 0x01}, // /
			{0x3e, 0x45, 0x49, 0x51, 0x3e}, // 0
			{0x00, 0x42, 0x7f, 0x40, 0x00}, // 1
			{0x62, 0x51, 0x49, 0x45, 0x42}, // 2
			{0x22, 0x41, 0x49, 0x49, 0x36}, // 3
			{0x08, 0x0c, 0x0a, 0x7f, 0x08}, // 4
			{0x2f, 0x49, 0x49, 0x49, 0x31}, // 5
			{0x3e, 0x49, 0x49, 0x49, 0x32}, // 6
			{0x01, 0x71, 0x09, 0x05, 0x03}, // 7
			{0x36, 0x49, 0x49, 0x49, 0x36}, // 8
			{0x26, 0x49, 0x49, 0x49, 0x3e}, // 9
			{0x00, 0x36, 0x36, 0x00, 0x00}, // :
			{0x00, 0x00, 0x36, 0x16, 0x00}, // ;
			{0x00, 0x08, 0x14, 0x22, 0x00}, // <
			{0x00, 0x14, 0x14, 0x14, 0x14}, // =
			{0x00, 0x22, 0x14, 0x08, 0x00}, // >
			{0x02, 0x01, 0x59, 0x05, 0x02}, // ?
			{0x3e, 0x41, 0x5d, 0x55, 0x5e}, // @
			{0x7e, 0x09, 0x09, 0x09, 0x7e}, // A
			{0x7f, 0x49, 0x49, 0x49, 0x36}, // B
			{0x3e, 0x41, 0x41, 0x41, 0x22}, // C
			{0x7f, 0x41, 0x41, 0x41, 0x3e}, // D
			{0x7f, 0x49, 0x49, 0x49, 0x41}, // E
			{0x7f, 0x09, 0x09, 0x09, 0x01}, // F
			{0x3e, 0x41, 0x49, 0x49, 0x3a}, // G
			{0x7f, 0x08, 0x08, 0x08, 0x7f}, // H
			{0x41, 0x41, 0x7f, 0x41, 0x41}, // I
			{0x20, 0x40, 0x40, 0x40, 0x3f}, // J
			{0x7f, 0x08, 0x14, 0x22, 0x41}, // K
			{0x7f, 0x40, 0x40, 0x40, 0x40}, // L
			{0x7f, 0x02, 0x0c, 0x02, 0x7f}, // M
			{0x7f, 0x04, 0x08, 0x10, 0x7f}, // N
			{0x3e, 0x41, 0x41, 0x41, 0x3e}, // O
			{0x7f, 0x09, 0x09, 0x09, 0x06}, // P
			{0x3e, 0x41, 0x51, 0x21, 0x5e}, // Q
			{0x7f, 0x09, 0x19, 0x29, 0x46}, // R
			{0x26, 0x49, 0x49, 0x49, 0x32}, // S
			{0x01, 0x01, 0x7f, 0x01, 0x01}, // T
			{0x3f, 0x40, 0x40, 0x40, 0x3f}, // U
			{0x07, 0x18, 0x60, 0x18, 0x07}, // V
			{0x1f, 0x60, 0x18, 0x60, 0x1f}, // W
			{0x63, 0x14, 0x08, 0x14, 0x63}, // X
			{0x07, 0x08, 0x70, 0x08, 0x07}, // Y
			{0x61, 0x51, 0x49, 0x45, 0x43}, // Z
			{0x00, 0x7f, 0x41, 0x41, 0x00}, // [
			{0x01, 0x06, 0x08, 0x30, 0x40}, //
			{0x00, 0x41, 0x41, 0x7f, 0x00}, // ]
			{0x04, 0x02, 0x01, 0x02, 0x04}, // ^
			{0x40, 0x40, 0x40, 0x40, 0x40}, // _
			{0x01, 0x03, 0x00, 0x00, 0x00}, // `
			{0x38, 0x44, 0x44, 0x24, 0x78}, // a
			{0x7f, 0x44, 0x44, 0x44, 0x38}, // b
			{0x38, 0x44, 0x44, 0x44, 0x28}, // c
			{0x38, 0x44, 0x44, 0x44, 0x7f}, // d
			{0x38, 0x54, 0x54, 0x54, 0x48}, // e
			{0x00, 0x08, 0x7e, 0x09, 0x02}, // f
			{0x18, 0xa4, 0xa4, 0xa4, 0x78}, // g
			{0x7f, 0x04, 0x04, 0x04, 0x78}, // h
			{0x00, 0x00, 0x7d, 0x40, 0x00}, // i
			{0x40, 0x80, 0x80, 0x7d, 0x00}, // j
			{0x00, 0x7f, 0x10, 0x28, 0x44}, // k
			{0x00, 0x00, 0x7f, 0x00, 0x00}, // l
			{0x78, 0x04, 0x18, 0x04, 0x78}, // m
			{0x7c, 0x08, 0x04, 0x04, 0x78}, // n
			{0x38, 0x44, 0x44, 0x44, 0x38}, // o
			{0xf8, 0x24, 0x24, 0x24, 0x18}, // p
			{0x18, 0x24, 0x24, 0x24, 0xf8}, // q
			{0x7c, 0x08, 0x04, 0x04, 0x04}, // r
			{0x48, 0x54, 0x54, 0x54, 0x24}, // s
			{0x04, 0x04, 0x7e, 0x44, 0x04}, // t
			{0x3c, 0x40, 0x40, 0x20, 0x7c}, // u
			{0x0c, 0x30, 0x40, 0x30, 0x0c}, // v
			{0x3c, 0x40, 0x30, 0x40, 0x3c}, // w
			{0x44, 0x28, 0x10, 0x28, 0x44}, // x
			{0x1c, 0xa0, 0xa0, 0xa0, 0x7c}, // y
			{0x44, 0x64, 0x54, 0x4c, 0x44}, // z
			{0x08, 0x08, 0x36, 0x41, 0x41}, // {
			{0x00, 0x00, 0x77, 0x00, 0x00}, // |
			{0x41, 0x41, 0x36, 0x08, 0x08}, // }
			{0x02, 0x01, 0x01, 0x02, 0x01}, // ~
			{0xaa, 0x55, 0xaa, 0x55, 0xaa} // checker
			}; 

	
	public Emulator() {
		setPreferredSize(new Dimension(280,180));
		setMinimumSize(new Dimension(280,180));
		setMaximumSize(new Dimension(280,180));
		//setText(Menu.active.startBlock.header);
		text += "abcdefghijklmnopqrstabcdefghijklmnopqrst\n";
		text += "abcdefghijklmnopqrstabcdefghijklmnopqrst\n";
		text += "abcdefghijklmnopqrstabcdefghijklmnopqrst\n";
		text += "abcdefghijklmnopqrstabcdefghijklmnopqrst";
		setText(text);
		
		addMouseListener(this);
	}
	
	public void setText(String text) {
		this.text = text;
		heading = "Emulator";
		repaint();
	}
	
	@Override
	public void paintComponent(Graphics gr) {
		super.paintComponent(gr);
		
		lcd_height = Menu.getInstance().getLCDRows()*3*8;
		
		Graphics2D g = (Graphics2D) gr.create();
		g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

		g.translate(4, 30);
		scale = (getWidth()-8)/400.0;
		g.scale(scale, scale);
		
		Color g1, g2;
		g1 = new Color(190,190,170);
		g2 = new Color(90,90,80);
		
		GradientPaint gp = new GradientPaint(
				0, 0, g1, 
				400, (int) 110 + lcd_height, g2);
		
		g.setPaint(gp);
		g.fillRoundRect(0, 0, 400, (int) 110 + lcd_height, 25, 25);
		
		g.setColor(Color.BLACK);
		g.fillRoundRect(10, 10, 400 - 20, (int) 30 + lcd_height, 10, 10);
		
		/*
		 * Draw buttons
		 */
		for (int i = 0; i < buttons.length; i++) {
			g.setColor(Color.DARK_GRAY);
			g.fillRoundRect(10 + i * 70, 45 + lcd_height, 60, 60, 10, 10);		

			g.setColor(Color.WHITE);
			Font org_font = g.getFont();
			g.setFont(new Font(org_font.getFontName(), org_font.getStyle(), 16));
			FontMetrics fm = g.getFontMetrics();
			Rectangle2D str_rect = fm.getStringBounds(buttons[i], null); 
			g.drawString(buttons[i], (int) (40 + i * 70 - str_rect.getWidth()/2), 60 + lcd_height);
			g.setFont(org_font);
			
			
			
			if (button_down != null && button_down == i) {
				g1 = new Color(255,0,0);
				g2 = new Color(170,0,0);
			}
			else {
				g1 = new Color(170,0,0);
				g2 = new Color(110,0,0);
			}
			
			gp = new GradientPaint(
					0, 65 + lcd_height, g1, 
					0, 65 + lcd_height + 45, g2);
			
			g.setPaint(gp);
			g.fillRoundRect(15 + i * 70, 65 + lcd_height, 50, 35, 20, 20);
		}
		
		/*
		 * Draw dot matrix text
		 */
		g.translate(16, 24);
		g.scale((400-2*4-2*10) / (double)(Menu.getInstance().getLCDCols()*3*6), 1);
		g.setColor(Color.BLACK);

		int col = 0;
		int row = 0;
		for (int i = 0; i < text.length(); i++) {
			if (text.toCharArray()[i] == '\n') {
				row++;
				if (row >= Menu.getInstance().getLCDRows())
					break;
				
				col = 0;
			}
			else {
				for (int y = 0; y < 8; y++) {
					for (int x = 0; x < 5; x++) {
						if (((font[text.toCharArray()[i]-32][x] >> (y)) & 1) > 0 && col < Menu.getInstance().getLCDCols()) {
							g.setColor(Color.GREEN);
							g.fillRect(x*3 + col*6*3, y*3 + row * 3*8, 2, 2);
						}
						else if (col < Menu.getInstance().getLCDCols()) {
							g.setColor(new Color(90,90,90));
							g.fillRect(x*3 + col*6*3, y*3 + row * 3*8, 2, 2);							
						}
					}
				}
				col++;
			}
		}
		
		g.dispose();
	}

	@Override
	public void mouseClicked(MouseEvent e) {}

	@Override
	public void mouseEntered(MouseEvent e) {}

	@Override
	public void mouseExited(MouseEvent e) {}

	@Override
	public void mousePressed(MouseEvent e) {
		button_down = null;
		
		for (int i = 0; i < buttons.length; i++) {
			if ((e.getX()-4)/scale > (15 + i*70) && (e.getX()-4)/scale < (65 + i*70) &&
				(e.getY()-30)/scale > (65 + lcd_height) && (e.getY()-30)/scale < (100 + lcd_height)) {
				
				//System.out.println(i);
				button_down = new Integer(i);
				repaint();
			}
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		button_down = null;
		repaint();
	}
}
